<!-- FlowableProperties.vue - Flowable属性配置组件 -->
<template>
  <div class="flowable-properties">
    <el-form :model="properties" label-width="120px" size="small">
      <!-- 基本属性 -->
      <el-collapse v-model="activeNames" class="property-collapse">
        <!-- 常规属性 -->
        <el-collapse-item title="常规" name="general">
          <el-form-item label="ID">
            <el-input 
              v-model="properties.id" 
              @blur="updateProperty('id', properties.id)"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="名称">
            <el-input 
              v-model="properties.name" 
              @blur="updateProperty('name', properties.name)"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="文档" v-if="showDocumentation">
            <el-input 
              type="textarea" 
              v-model="properties.documentation"
              @blur="updateProperty('documentation', properties.documentation)"
              :rows="3"
              :disabled="!canEdit"
            />
          </el-form-item>
        </el-collapse-item>

        <!-- 流程属性（仅流程元素） -->
        <el-collapse-item title="流程" name="process" v-if="isProcess">
          <el-form-item label="流程键">
            <el-input 
              v-model="properties.processKey" 
              @blur="updateProperty('processKey', properties.processKey)"
              placeholder="唯一标识符"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="版本标签">
            <el-input 
              v-model="properties.versionTag" 
              @blur="updateProperty('versionTag', properties.versionTag)"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="可执行">
            <el-switch 
              v-model="properties.isExecutable" 
              @change="updateProperty('isExecutable', properties.isExecutable)"
              :disabled="!canEdit"
            />
          </el-form-item>
        </el-collapse-item>

        <!-- 用户任务属性 -->
        <el-collapse-item title="用户任务" name="userTask" v-if="isUserTask">
          <el-form-item label="办理人">
            <el-input 
              v-model="properties.assignee" 
              @blur="updateProperty('assignee', properties.assignee)"
              placeholder="#{userId} 或表达式"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="候选用户">
            <el-input 
              v-model="properties.candidateUsers" 
              @blur="updateProperty('candidateUsers', properties.candidateUsers)"
              placeholder="user1,user2 或 #{userList}"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="候选组">
            <el-input 
              v-model="properties.candidateGroups" 
              @blur="updateProperty('candidateGroups', properties.candidateGroups)"
              placeholder="group1,group2 或 #{groupList}"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="优先级">
            <el-input-number 
              v-model="properties.priority" 
              @change="updateProperty('priority', properties.priority)"
              :min="0"
              :max="100"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="到期日期">
            <el-input 
              v-model="properties.dueDate" 
              @blur="updateProperty('dueDate', properties.dueDate)"
              placeholder="ISO8601格式 或 表达式"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="类别">
            <el-input 
              v-model="properties.category" 
              @blur="updateProperty('category', properties.category)"
              :disabled="!canEdit"
            />
          </el-form-item>
        </el-collapse-item>

        <!-- 服务任务属性 -->
        <el-collapse-item title="服务任务" name="serviceTask" v-if="isServiceTask">
          <el-form-item label="实现方式">
            <el-radio-group 
              v-model="properties.implementationType" 
              @change="updateProperty('implementationType', properties.implementationType)"
              :disabled="!canEdit"
            >
              <el-radio label="class">Java类</el-radio>
              <el-radio label="expression">表达式</el-radio>
              <el-radio label="delegateExpression">委托表达式</el-radio>
            </el-radio-group>
          </el-form-item>
          
          <el-form-item label="Java类" v-if="properties.implementationType === 'class'">
            <el-input 
              v-model="properties.javaClass" 
              @blur="updateProperty('javaClass', properties.javaClass)"
              placeholder="com.example.ServiceDelegate"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="表达式" v-if="properties.implementationType === 'expression'">
            <el-input 
              v-model="properties.expression" 
              @blur="updateProperty('expression', properties.expression)"
              placeholder="#{serviceBean.execute(execution)}"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="委托表达式" v-if="properties.implementationType === 'delegateExpression'">
            <el-input 
              v-model="properties.delegateExpression" 
              @blur="updateProperty('delegateExpression', properties.delegateExpression)"
              placeholder="#{serviceDelegate}"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="结果变量">
            <el-input 
              v-model="properties.resultVariable" 
              @blur="updateProperty('resultVariable', properties.resultVariable)"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="异步执行">
            <el-switch 
              v-model="properties.async" 
              @change="updateProperty('async', properties.async)"
              :disabled="!canEdit"
            />
          </el-form-item>
        </el-collapse-item>

        <!-- 脚本任务属性 -->
        <el-collapse-item title="脚本任务" name="scriptTask" v-if="isScriptTask">
          <el-form-item label="脚本格式">
            <el-select 
              v-model="properties.scriptFormat" 
              @change="updateProperty('scriptFormat', properties.scriptFormat)"
              placeholder="选择脚本语言"
              :disabled="!canEdit"
            >
              <el-option label="JavaScript" value="javascript" />
              <el-option label="Groovy" value="groovy" />
              <el-option label="JRuby" value="jruby" />
              <el-option label="Jython" value="jython" />
            </el-select>
          </el-form-item>
          
          <el-form-item label="脚本内容">
            <el-input 
              type="textarea" 
              v-model="properties.script"
              @blur="updateProperty('script', properties.script)"
              :rows="6"
              placeholder="输入脚本代码"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="结果变量">
            <el-input 
              v-model="properties.resultVariable" 
              @blur="updateProperty('resultVariable', properties.resultVariable)"
              :disabled="!canEdit"
            />
          </el-form-item>
        </el-collapse-item>

        <!-- 网关属性 -->
        <el-collapse-item title="网关" name="gateway" v-if="isGateway">
          <el-form-item label="默认流向" v-if="isExclusiveGateway">
            <el-select 
              v-model="properties.defaultFlow" 
              @change="updateProperty('defaultFlow', properties.defaultFlow)"
              placeholder="选择默认流向"
              :disabled="!canEdit"
            >
              <el-option 
                v-for="flow in outgoingFlows"
                :key="flow.id"
                :label="flow.name || flow.id"
                :value="flow.id"
              />
            </el-select>
          </el-form-item>
        </el-collapse-item>

        <!-- 序列流属性 -->
        <el-collapse-item title="序列流" name="sequenceFlow" v-if="isSequenceFlow">
          <el-form-item label="条件表达式">
            <el-input 
              type="textarea"
              v-model="properties.conditionExpression" 
              @blur="updateProperty('conditionExpression', properties.conditionExpression)"
              placeholder="#{condition}"
              :rows="3"
              :disabled="!canEdit"
            />
          </el-form-item>
          
          <el-form-item label="跳过表达式">
            <el-input 
              v-model="properties.skipExpression" 
              @blur="updateProperty('skipExpression', properties.skipExpression)"
              placeholder="#{skipCondition}"
              :disabled="!canEdit"
            />
          </el-form-item>
        </el-collapse-item>

        <!-- 多实例属性 -->
        <el-collapse-item title="多实例" name="multiInstance" v-if="supportsMultiInstance">
          <el-form-item label="多实例类型">
            <el-radio-group 
              v-model="properties.multiInstanceType" 
              @change="updateProperty('multiInstanceType', properties.multiInstanceType)"
              :disabled="!canEdit"
            >
              <el-radio label="">无</el-radio>
              <el-radio label="sequential">串行</el-radio>
              <el-radio label="parallel">并行</el-radio>
            </el-radio-group>
          </el-form-item>
          
          <template v-if="properties.multiInstanceType">
            <el-form-item label="集合">
              <el-input 
                v-model="properties.collection" 
                @blur="updateProperty('collection', properties.collection)"
                placeholder="#{userList}"
                :disabled="!canEdit"
              />
            </el-form-item>
            
            <el-form-item label="元素变量">
              <el-input 
                v-model="properties.elementVariable" 
                @blur="updateProperty('elementVariable', properties.elementVariable)"
                placeholder="user"
                :disabled="!canEdit"
              />
            </el-form-item>
            
            <el-form-item label="完成条件">
              <el-input 
                v-model="properties.completionCondition" 
                @blur="updateProperty('completionCondition', properties.completionCondition)"
                placeholder="#{nrOfCompletedInstances/nrOfInstances >= 0.6}"
                :disabled="!canEdit"
              />
            </el-form-item>
          </template>
        </el-collapse-item>

        <!-- 扩展属性 -->
        <el-collapse-item title="扩展属性" name="extensions">
          <div class="extension-properties">
            <div class="extension-header">
              <span>自定义属性</span>
              <el-button 
                type="primary" 
                size="small" 
                @click="addExtensionProperty"
                :disabled="!canEdit"
              >
                添加
              </el-button>
            </div>
            
            <div 
              v-for="(prop, index) in properties.extensionProperties" 
              :key="index"
              class="extension-item"
            >
              <el-input 
                v-model="prop.name"
                placeholder="属性名"
                size="small"
                :disabled="!canEdit"
                @blur="updateExtensionProperty(index, 'name', prop.name)"
              />
              <el-input 
                v-model="prop.value"
                placeholder="属性值"
                size="small"
                :disabled="!canEdit"
                @blur="updateExtensionProperty(index, 'value', prop.value)"
              />
              <el-button 
                type="danger" 
                size="small" 
                @click="removeExtensionProperty(index)"
                :disabled="!canEdit"
              >
                删除
              </el-button>
            </div>
          </div>
        </el-collapse-item>
      </el-collapse>
    </el-form>
  </div>
</template>

<script setup lang="ts">
import { ref, reactive, computed, watch, onMounted } from 'vue'
import type { Ref } from 'vue'

// Props
interface Props {
  element: any
  modeler: any
  readonly?: boolean
}

const props = withDefaults(defineProps<Props>(), {
  readonly: false
})

// Emits
const emit = defineEmits<{
  propertyChange: [property: string, value: any]
}>()

// 响应式数据
const activeNames = ref(['general'])
const properties = reactive({
  id: '',
  name: '',
  documentation: '',
  // 流程属性
  processKey: '',
  versionTag: '',
  isExecutable: true,
  // 用户任务属性
  assignee: '',
  candidateUsers: '',
  candidateGroups: '',
  priority: 50,
  dueDate: '',
  category: '',
  // 服务任务属性
  implementationType: 'class',
  javaClass: '',
  expression: '',
  delegateExpression: '',
  resultVariable: '',
  async: false,
  // 脚本任务属性
  scriptFormat: 'javascript',
  script: '',
  // 网关属性
  defaultFlow: '',
  // 序列流属性
  conditionExpression: '',
  skipExpression: '',
  // 多实例属性
  multiInstanceType: '',
  collection: '',
  elementVariable: '',
  completionCondition: '',
  // 扩展属性
  extensionProperties: [] as Array<{name: string, value: string}>
})

// 计算属性
const canEdit = computed(() => !props.readonly)

const isProcess = computed(() => props.element?.type === 'bpmn:Process')
const isUserTask = computed(() => props.element?.type === 'bpmn:UserTask')
const isServiceTask = computed(() => props.element?.type === 'bpmn:ServiceTask')
const isScriptTask = computed(() => props.element?.type === 'bpmn:ScriptTask')
const isGateway = computed(() => 
  props.element?.type?.includes('Gateway')
)
const isExclusiveGateway = computed(() => 
  props.element?.type === 'bpmn:ExclusiveGateway'
)
const isSequenceFlow = computed(() => 
  props.element?.type === 'bpmn:SequenceFlow'
)

const supportsMultiInstance = computed(() => 
  ['bpmn:UserTask', 'bpmn:ServiceTask', 'bpmn:ScriptTask', 'bpmn:CallActivity'].includes(props.element?.type)
)

const showDocumentation = computed(() => 
  props.element && props.element.type !== 'bpmn:SequenceFlow'
)

const outgoingFlows = computed(() => {
  if (!props.element || !props.element.outgoing) return []
  return props.element.outgoing.map((flow: any) => ({
    id: flow.id,
    name: flow.businessObject?.name || flow.id
  }))
})

// 监听元素变化
watch(() => props.element, (newElement) => {
  if (newElement) {
    loadElementProperties(newElement)
  }
}, { immediate: true })

// 加载元素属性
const loadElementProperties = (element: any) => {
  if (!element || !element.businessObject) return

  const bo = element.businessObject
  
  // 基本属性
  properties.id = bo.id || ''
  properties.name = bo.name || ''
  properties.documentation = getDocumentation(bo)
  
  // 流程属性
  if (isProcess.value) {
    properties.processKey = bo.id || ''
    properties.versionTag = bo.versionTag || ''
    properties.isExecutable = bo.isExecutable !== false
  }
  
  // 用户任务属性
  if (isUserTask.value) {
    properties.assignee = bo.assignee || ''
    properties.candidateUsers = bo.candidateUsers || ''
    properties.candidateGroups = bo.candidateGroups || ''
    properties.priority = bo.priority || 50
    properties.dueDate = bo.dueDate || ''
    properties.category = bo.category || ''
  }
  
  // 服务任务属性
  if (isServiceTask.value) {
    if (bo.class) {
      properties.implementationType = 'class'
      properties.javaClass = bo.class
    } else if (bo.expression) {
      properties.implementationType = 'expression'
      properties.expression = bo.expression
    } else if (bo.delegateExpression) {
      properties.implementationType = 'delegateExpression'
      properties.delegateExpression = bo.delegateExpression
    }
    properties.resultVariable = bo.resultVariable || ''
    properties.async = bo.async === true
  }
  
  // 脚本任务属性
  if (isScriptTask.value) {
    properties.scriptFormat = bo.scriptFormat || 'javascript'
    properties.script = bo.script || ''
    properties.resultVariable = bo.resultVariable || ''
  }
  
  // 网关属性
  if (isExclusiveGateway.value) {
    properties.defaultFlow = bo.default?.id || ''
  }
  
  // 序列流属性
  if (isSequenceFlow.value) {
    properties.conditionExpression = getConditionExpression(bo)
    properties.skipExpression = bo.skipExpression || ''
  }
  
  // 多实例属性
  if (supportsMultiInstance.value) {
    const loopCharacteristics = bo.loopCharacteristics
    if (loopCharacteristics) {
      properties.multiInstanceType = loopCharacteristics.isSequential ? 'sequential' : 'parallel'
      properties.collection = loopCharacteristics.collection || ''
      properties.elementVariable = loopCharacteristics.elementVariable || ''
      properties.completionCondition = loopCharacteristics.completionCondition?.body || ''
    } else {
      properties.multiInstanceType = ''
    }
  }
  
  // 扩展属性
  loadExtensionProperties(bo)
}

// 获取文档
const getDocumentation = (bo: any): string => {
  if (bo.documentation && bo.documentation.length > 0) {
    return bo.documentation[0].text || ''
  }
  return ''
}

// 获取条件表达式
const getConditionExpression = (bo: any): string => {
  if (bo.conditionExpression) {
    return bo.conditionExpression.body || ''
  }
  return ''
}

// 加载扩展属性
const loadExtensionProperties = (bo: any) => {
  properties.extensionProperties = []
  
  if (bo.extensionElements && bo.extensionElements.values) {
    const properties_element = bo.extensionElements.values.find((el: any) => 
      el.$type === 'flowable:Properties'
    )
    
    if (properties_element && properties_element.values) {
      properties.extensionProperties = properties_element.values.map((prop: any) => ({
        name: prop.name || '',
        value: prop.value || ''
      }))
    }
  }
}

// 更新属性
const updateProperty = (property: string, value: any) => {
  if (!props.element || !props.modeler) return

  const modeling = props.modeler.get('modeling')
  const elementRegistry = props.modeler.get('elementRegistry')
  
  const element = elementRegistry.get(props.element.id)
  if (!element) return

  const updateObj: any = {}
  
  switch (property) {
    case 'id':
      modeling.updateProperties(element, { id: value })
      break
    case 'name':
      modeling.updateProperties(element, { name: value })
      break
    case 'documentation':
      updateDocumentation(element, value)
      break
    case 'assignee':
    case 'candidateUsers':
    case 'candidateGroups':
    case 'priority':
    case 'dueDate':
    case 'category':
      updateObj[property] = value
      modeling.updateProperties(element, updateObj)
      break
    case 'javaClass':
      modeling.updateProperties(element, { 'class': value })
      break
    case 'expression':
    case 'delegateExpression':
    case 'resultVariable':
    case 'async':
      updateObj[property] = value
      modeling.updateProperties(element, updateObj)
      break
    case 'scriptFormat':
    case 'script':
      updateObj[property] = value
      modeling.updateProperties(element, updateObj)
      break
    case 'conditionExpression':
      updateConditionExpression(element, value)
      break
    case 'multiInstanceType':
      updateMultiInstance(element, value)
      break
    case 'collection':
    case 'elementVariable':
    case 'completionCondition':
      updateMultiInstanceProperty(element, property, value)
      break
    default:
      updateObj[property] = value
      modeling.updateProperties(element, updateObj)
  }
  
  emit('propertyChange', property, value)
}

// 更新文档
const updateDocumentation = (element: any, text: string) => {
  const modeling = props.modeler.get('modeling')
  const bpmnFactory = props.modeler.get('bpmnFactory')
  
  let documentation
  if (text) {
    documentation = bpmnFactory.create('bpmn:Documentation', {
      text: text
    })
  }
  
  modeling.updateProperties(element, {
    documentation: text ? [documentation] : []
  })
}

// 更新条件表达式
const updateConditionExpression = (element: any, expression: string) => {
  const modeling = props.modeler.get('modeling')
  const bpmnFactory = props.modeler.get('bpmnFactory')
  
  let conditionExpression
  if (expression) {
    conditionExpression = bpmnFactory.create('bpmn:FormalExpression', {
      body: expression
    })
  }
  
  modeling.updateProperties(element, {
    conditionExpression: expression ? conditionExpression : undefined
  })
}

// 更新多实例
const updateMultiInstance = (element: any, type: string) => {
  const modeling = props.modeler.get('modeling')
  const bpmnFactory = props.modeler.get('bpmnFactory')
  
  let loopCharacteristics
  if (type) {
    loopCharacteristics = bpmnFactory.create('bpmn:MultiInstanceLoopCharacteristics', {
      isSequential: type === 'sequential'
    })
  }
  
  modeling.updateProperties(element, {
    loopCharacteristics: type ? loopCharacteristics : undefined
  })
}

// 更新多实例属性
const updateMultiInstanceProperty = (element: any, property: string, value: any) => {
  const bo = element.businessObject
  if (!bo.loopCharacteristics) return

  const modeling = props.modeler.get('modeling')
  const bpmnFactory = props.modeler.get('bpmnFactory')
  
  const updateObj: any = {}
  
  if (property === 'completionCondition') {
    if (value) {
      updateObj.completionCondition = bpmnFactory.create('bpmn:FormalExpression', {
        body: value
      })
    } else {
      updateObj.completionCondition = undefined
    }
  } else {
    updateObj[property] = value || undefined
  }
  
  modeling.updateProperties(bo.loopCharacteristics, updateObj)
}

// 扩展属性管理
const addExtensionProperty = () => {
  properties.extensionProperties.push({ name: '', value: '' })
}

const removeExtensionProperty = (index: number) => {
  properties.extensionProperties.splice(index, 1)
  updateExtensionProperties()
}

const updateExtensionProperty = (index: number, field: string, value: string) => {
  properties.extensionProperties[index][field as keyof typeof properties.extensionProperties[0]] = value
  updateExtensionProperties()
}

const updateExtensionProperties = () => {
  if (!props.element || !props.modeler) return

  const modeling = props.modeler.get('modeling')
  const bpmnFactory = props.modeler.get('bpmnFactory')
  const elementRegistry = props.modeler.get('elementRegistry')
  
  const element = elementRegistry.get(props.element.id)
  if (!element) return

  // 创建扩展属性
  const extensionElements = bpmnFactory.create('bpmn:ExtensionElements')
  const propertiesElement = bpmnFactory.create('flowable:Properties')
  
  propertiesElement.values = properties.extensionProperties
    .filter(prop => prop.name && prop.value)
    .map(prop => bpmnFactory.create('flowable:Property', {
      name: prop.name,
      value: prop.value
    }))
  
  if (propertiesElement.values.length > 0) {
    extensionElements.values = [propertiesElement]
    modeling.updateProperties(element, { extensionElements })
  } else {
    modeling.updateProperties(element, { extensionElements: undefined })
  }
}

onMounted(() => {
  if (props.element) {
    loadElementProperties(props.element)
  }
})
</script>

<style scoped lang="scss">
.flowable-properties {
  height: 100%;
  overflow-y: auto;

  .property-collapse {
    border: none;

    :deep(.el-collapse-item__header) {
      background: #f8f9fa;
      border-bottom: 1px solid #e9ecef;
      font-weight: 500;
    }

    :deep(.el-collapse-item__content) {
      padding: 15px 10px;
    }
  }

  .extension-properties {
    .extension-header {
      display: flex;
      justify-content: space-between;
      align-items: center;
      margin-bottom: 10px;
      font-weight: 500;
    }

    .extension-item {
      display: flex;
      gap: 8px;
      margin-bottom: 8px;
      align-items: center;

      .el-input {
        flex: 1;
      }
    }
  }

  .el-form-item {
    margin-bottom: 15px;

    :deep(.el-form-item__label) {
      font-size: 12px;
      color: #606266;
    }
  }

  .el-input,
  .el-select,
  .el-input-number {
    :deep(.el-input__inner) {
      font-size: 12px;
    }
  }

  .el-textarea {
    :deep(.el-textarea__inner) {
      font-size: 12px;
      font-family: 'Monaco', 'Consolas', monospace;
    }
  }
}